part of './taro_api.dart';

class _TaroNetworkApi {
  Future<TaroNetworkResponse> request(
    String url, {
    dynamic data,
    Map header,
    String method,
  }) {
    Completer completer = Completer();
    TaroApi.global.callMethod('request', [
      TaroApi.jsify({
        'url': url,
        'data': data,
        'header': header,
        'method': method ?? 'GET',
        'responseType': 'arraybuffer',
        'fail': (JsObject res) {
          completer.completeError(res.toString());
        },
        'success': (JsObject res) {
          completer.complete(TaroNetworkResponse(res));
        },
      })
    ]);
    return completer.future;
  }

  TaroDownloadTask downloadFile(
    String url, {
    String filePath,
    Map header,
    Function(TaroDownloadFileSuccessResult result) success,
    Function(String reason) fail,
  }) {
    final handler = TaroApi.global.callMethod('downloadFile', [
      TaroApi.jsify({
        'url': url,
        'filePath': filePath,
        'header': header,
        'fail': (JsObject res) {
          fail?.call(res.toString());
        },
        'success': (JsObject res) {
          success?.call(TaroDownloadFileSuccessResult(res));
        },
      })
    ]);
    return TaroDownloadTask(handler);
  }

  TaroUploadTask uploadFile(
    String url, {
    String filePath,
    String name,
    Map header,
    Map formData,
    Duration timeout,
    Function(TaroUploadFileSuccessResult result) success,
    Function(String reason) fail,
  }) {
    final handler = TaroApi.global.callMethod('uploadFile', [
      TaroApi.jsify({
        'url': url,
        'filePath': filePath,
        'header': header,
        'fail': (JsObject res) {
          fail?.call(res.toString());
        },
        'success': (JsObject res) {
          success?.call(TaroUploadFileSuccessResult(res));
        },
      })
    ]);
    return TaroUploadTask(handler);
  }

  Future<TaroWebSocket> connectSocket(
    String url, {
    Map header,
    List<String> protocols,
    bool tcpNoDelay,
  }) async {
    final handler = TaroApi.global.callMethod('connectSocket', [
      TaroApi.jsify({
        'url': url,
        'header': header,
        'protocols': protocols,
        'tcpNoDelay': tcpNoDelay,
      })
    ]);
    return TaroWebSocket(await TaroApi.wrapPromise(handler));
  }
}

class TaroNetworkResponse {
  final JsObject data;
  final Uint8List _uint8list;

  TaroNetworkResponse(this.data)
      : _uint8list =
            base64.decode(TaroApi.base.arrayBufferToBase64(data['data']));

  int get statusCode => data['statusCode'];

  Map get header => TaroApi.jsonify(data['header']);

  String get errMsg => data['errMsg'];

  Uint8List asUint8List() {
    return _uint8list;
  }

  String asString() {
    return utf8.decode(_uint8list);
  }

  dynamic asJson() {
    return json.decode(asString());
  }
}

class TaroDownloadTask {
  final JsObject data;
  TaroDownloadTask(this.data);

  abort() {
    data.callMethod('abort');
  }
}

class TaroDownloadFileSuccessResult {
  final JsObject data;
  TaroDownloadFileSuccessResult(this.data);

  String get filePath => data['filePath'];

  int get statusCode => data['statusCode'];

  String get tempFilePath => data['tempFilePath'];

  String get errMsg => data['errMsg'];
}

class TaroUploadTask {
  final JsObject data;
  TaroUploadTask(this.data);

  abort() {
    data.callMethod('abort');
  }
}

class TaroUploadFileSuccessResult {
  final JsObject _data;
  TaroUploadFileSuccessResult(this._data);

  String get data => _data['data'];

  int get statusCode => _data['statusCode'];

  String get errMsg => _data['errMsg'];
}

class TaroWebSocket {
  final JsObject data;
  TaroWebSocket(this.data);

  void onOpen(Function callback) {
    data.callMethod('onOpen', [
      (res) {
        print(res);
        callback();
      }
    ]);
  }

  void onMessage(Function(dynamic message) callback) {
    data.callMethod('onMessage', [
      (JsObject res) {
        callback(TaroApi.jsonify(res));
      }
    ]);
  }

  void onError(Function callback) {
    data.callMethod('onError', [
      (res) {
        callback();
      }
    ]);
  }

  void onClose(Function(dynamic reason) callback) {
    data.callMethod('onClose', [
      (JsObject res) {
        callback(TaroApi.jsonify(res));
      }
    ]);
  }

  void send(dynamic message) {
    if (message is String) {
      data.callMethod('send', [
        TaroApi.jsify({'data': message})
      ]);
    } else {
      data.callMethod('send', [TaroApi.jsify(message)]);
    }
  }

  void close() {
    data.callMethod('close');
  }
}
